/* 
	@Copyright (c) 2007 by Denis Riabtchik. All rights reserved. See license.txt and http://jgrouse.com for details@
	$Id: CommentTag.java 573 2009-02-28 19:34:41Z denis.riabtchik $
*/

package jgrouse.jgdoc.elements;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import jgrouse.jgdoc.Vocabulary;
import jgrouse.jgdoc.api.IComment;
import jgrouse.jgdoc.api.ICommentTag;
import jgrouse.jgdoc.api.IContent;
import jgrouse.jgdoc.api.ILink;

public class CommentTag implements ICommentTag, Serializable
{
	private static final long serialVersionUID = 3016975659089559834L;
	private Vocabulary m_tagType;
	private IContent m_content;
	private String m_type;
	private String m_name;
	private IContent m_typeLink;
	private ILink m_nameLink;
	private Set<String> m_modifiers;
	private List<ICommentTag> m_children;
	private IComment m_comment;
	
	
	public CommentTag(Vocabulary pTagType, IContent pContent, String pType, String pName, Set<String> pModifiers, IComment pComment)
	{
		super();
		m_tagType = pTagType;
		m_content = pContent;
		m_type = pType;
		setName(pName);
		m_modifiers = pModifiers;
		m_children = new ArrayList<ICommentTag>();
		m_comment = pComment;
	}
	
	public String toString()
	{
		return toString(true);
	}
	
	public String toString(boolean renderChildren)
	{
		StringBuffer buf = new StringBuffer("<tagContent");
		buf.append(" tagType=\"").append(m_tagType.toString().toLowerCase()).append("\" ");
		if (m_typeLink != null)
		{
			buf.append(" type=\"").append(m_typeLink.toString()).append("\"");
		}
		if (m_name != null && !m_tagType.isNameAsDesc())
		{
			if (m_nameLink != null && m_nameLink.getResolvedPath() != null)
			{
				buf.append(" name=\"").append(m_nameLink.getResolvedPath()).append("\"");
			}
			else
			{
				buf.append(" name=\"").append(m_name).append("\"");
			}
		}
		buf.append(">");
		if (m_name != null && m_tagType.isNameAsDesc())
		{
			buf.append("<name><![CDATA[").append(m_name.trim()).append("]]></name>");
		}
		if (m_children.size() > 0 && renderChildren)
		{
			buf.append("<tagChildren>");
			for (ICommentTag child : m_children)
			{
				buf.append(child.toString());
			}
			buf.append("</tagChildren>");
		}
		buf.append(m_content.toString()).append("</tagContent>");
		return buf.toString();
	}
	
	private IContent processType()
	{
		IContent c = new Content();
		StringTokenizer st = new StringTokenizer(m_type, "[]", true);
		while (st.hasMoreElements())
		{
			String token = st.nextToken();
			if ("[".equals(token) || "]".equals(token))
			{
				c.addContentSection(new ContentSection(token));
			}
			else
			{
				c.addContentSection(new Link(token, token, m_comment));
			}
		}
		return c;
	}
	
	public List<ILink> collectLinks(List<ILink> pList)
	{
		if (m_type != null)
		{
			//m_typeLink = new Link(m_type, m_type);
			//pList.add(m_typeLink);
			m_typeLink = processType();
			m_typeLink.collectLinks(pList);
		}
		if (m_tagType.isNameAsLink() && m_nameLink == null)
		{
			m_nameLink = new Link(m_name, m_name, m_comment);
		}
		if (m_nameLink != null)
		{
			pList.add(m_nameLink);
			m_content.addContentSection(0, m_nameLink);
		}
		if (m_content != null)
		{
			m_content.collectLinks(pList);
		}
		for (ICommentTag child : m_children)
		{
			child.collectLinks(pList);
		}
		return pList;
	}
	

	public IContent getContent()
	{
		return m_content;
	}

	/* (non-Javadoc)
	 * @see jgrouse.jgdoc.elements.ICommentTag#getTagType()
	 */
	public Vocabulary getTagType()
	{
		return m_tagType;
	}

	/* (non-Javadoc)
	 * @see jgrouse.jgdoc.elements.ICommentTag#getType()
	 */
	public String getType()
	{
		return m_type;
	}
	
	public void setContent(IContent pContent)
	{
		m_content = pContent;
	}

	/* (non-Javadoc)
	 * @see jgrouse.jgdoc.elements.ICommentTag#getName()
	 */
	public String getName()
	{
		return m_name;
	}

	public void setName(String pName)
	{
		m_name = pName;
	}

	public IContent getTypeLink()
	{
		return m_typeLink;
	}

	public ILink getNameLink()
	{
		return m_nameLink;
	}

	public Set<String> getModifiers()
	{
		return m_modifiers;
	}
	
	public boolean hasModifier(String pModifier)
	{
		return m_modifiers != null && m_modifiers.contains(pModifier);
	}
	

	public void addChild(ICommentTag pChild)
	{
		m_children.add(pChild);
	}

	public List<ICommentTag> getChildren()
	{
		return m_children;
	}
	
	public void resetPrivateModifier(String pPrivatePrefix)
	{
		if (pPrivatePrefix != null && (m_tagType.getTokenType().isTagType() || m_tagType == Vocabulary.PARAMOPTION))
		{
			String name = getName();
			if (name != null && name.indexOf(pPrivatePrefix) == 0 && (m_modifiers == null || !m_modifiers.contains("public")) && m_tagType.getModifiers().contains("private"))
			{
				if (m_modifiers == null)
				{
					m_modifiers = new HashSet<String>();
				}
				m_modifiers.add("private");
			}
		}		
	}

	public String getStrModifiers()
	{
		StringBuffer buf = new StringBuffer();
		Set<String> modifiers = getModifiers();
		if (modifiers != null && modifiers.size() > 0)
		{
			modifiers = new LinkedHashSet<String>(modifiers);
			modifiers.remove("optional");
			if (modifiers.size() > 0)
			{
				int i = 0;
				for (String s : modifiers)
				{
					if (s.length() > 0)
					{
						if (i > 0)
						{
							buf.append(' ');
						}
						buf.append(s);
						i++;
					}
				}
			}
		}
		return buf.toString();		
	}
}
